
#include "Http_Lib.h"
#include "String_Manip.h"
#include <stdio.h>
#include <windows.h>

int Connect(const char* server_name, int port, SOCKET* connect_socket)
{
	int retval;
	unsigned int addr;
	struct sockaddr_in server;
	struct hostent *hp;
	WSADATA wsaData;
	SOCKET conn_socket;

	if((retval = WSAStartup(0x202,&wsaData))!=0)
	{
        fprintf(stderr,"WSAStartup failed with error %d\n",retval);
        WSACleanup();
        return -1;
    }

	if(port == 0)
		printf("no port specified, default port 80 will be used\n");

	if(isalpha(server_name[0]))
		hp = gethostbyname(server_name);
	else
	{
		addr = inet_addr(server_name);
		hp = gethostbyaddr((char*)&addr,4,AF_INET);
	}

    if (hp == NULL ) 
	{
        fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",server_name,WSAGetLastError());
        WSACleanup();
        return -1;
    }
	memset(&server,0,sizeof(server));
	memcpy(&(server.sin_addr),hp->h_addr_list[0],hp->h_length);
	server.sin_family = hp->h_addrtype;
	server.sin_port = htons(port?port:DEFAULT_PORT);

	conn_socket = socket(AF_INET,DEFAULT_PROTO,0);
	if(conn_socket < 0)
	{
	    fprintf(stderr,"Client: Error Opening socket: Error %d\n",WSAGetLastError());
        WSACleanup();
        return -1;
    }
	printf("Client connecting to: %s\n",hp->h_name);
	if( connect(conn_socket,(struct sockaddr*)&server,sizeof(server))==SOCKET_ERROR)
	{
		fprintf(stderr,"Connecting Error: %d\n",WSAGetLastError());
        WSACleanup();
        return -1;
    }
	*connect_socket = conn_socket;
	printf("%s connected\n",hp->h_name);
	return 0;
}

int HttpParse(char* response, int recv_len, SOCKET conn_socket, const char* filename, FILE* fHandle)
{
	char* start;
	char* buffer_sent;
	char* buffer_word;
	int resp_num, is_partial = 0;
	long int cont_len, body_to_write, retval, already_write=0;

	start = response;
	buffer_sent = (char*)GetSentence(&response);
	printf("%s\n",buffer_sent);
	buffer_word = (char*)GetWord(&buffer_sent);
	buffer_word = (char*)GetWord(&buffer_sent);
	resp_num = atoi(buffer_word);
	switch(resp_num)
	{
	case 200:	//OK
		break;
	case 206:
		break;
	case 400:	//
		printf("Bad Request\n");
		return -1;
	case 416:
		printf("Requested Range Not Satisfiable\n");
		return -1;
	default:
		printf("status-code is %d, disposal is required\n",resp_num);
		return -1;
	}
	for(;;)
	{
		buffer_sent = (char*) GetSentence(&response);
		printf("%s\n",buffer_sent);
		if(!strcmp(buffer_sent,"\r"))
			break;
		buffer_word = (char*) GetWord(&buffer_sent);
		if(!strcmp(buffer_word,"Content-Length:"))
			cont_len = atoi(buffer_sent);
	}

	body_to_write = recv_len -(response-start);
	retval = WriteToFile(filename, cont_len, body_to_write, conn_socket, response, fHandle);
	return retval?-1:0;
}

int WriteToFile(const char* filename, int cont_len, int body_to_write, SOCKET conn_socket,char* response, FILE* fHandle)
{
	char buffer[65536];
	int already_write,write;
	already_write = 0;

	if((write=fwrite(response,sizeof(char),body_to_write,fHandle))<body_to_write)
	{
		printf("some error occurs when writting to file\n, %d",GetLastError());
		fclose(fHandle);
		return -1;
	}
	already_write += body_to_write;

	while(already_write < cont_len)
	{
		body_to_write = recv(conn_socket,buffer,65535,0);
		if(body_to_write == SOCKET_ERROR)
		{
			printf("some error occurs when receiving left portion of the body\n");
			fclose(fHandle);
			return -1;
		}
		if(fwrite(buffer,sizeof(char),body_to_write,fHandle)<body_to_write)
		{
			printf("some error occurs when writting to file\n");
			fclose(fHandle);
			return -1;
		}
		already_write+=body_to_write;
	}
	printf("Download finished\n");
	fclose(fHandle);
	return 0;
}




int HttpGet(const char* server_name, int port, char* fullpathname, char* storepath)
{
	SOCKET conn_socket;
	int retval;
	char buffer[65536];
	char* cur_pos;
	char* file_name;
	char _file_name[1024];
	FILE* fHandle;
	int cur_len, exist_file_size;
	retval = Connect(server_name,port,&conn_socket);
	if(retval != 0)
	{
		printf("The error code number is %d\n",retval);
		return -1;
	}

	file_name = (char*) GetFilename(fullpathname);
	sprintf(_file_name,"%s%s",storepath,file_name);
	if(fopen_s(&fHandle,_file_name,"ab")!=0)
		return -1;
	fseek(fHandle,0,SEEK_END);
	exist_file_size = ftell(fHandle);

	if(exist_file_size == 0)
		sprintf(buffer,"GET %s HTTP/1.0\r\nHost: %s\r\nAccept: */*\r\nConnection: close\r\n\n",fullpathname,server_name);
	else
		sprintf(buffer,"GET %s HTTP/1.0\r\nHost: %s\r\nAccept: */*\r\nRange: bytes=%d-\r\nConnection: close\r\n\n",fullpathname,server_name,exist_file_size);
	printf("%s\n",buffer);
	retval = 0;
	cur_len = (int)strlen(buffer);
	cur_pos = buffer;
	retval = send(conn_socket,buffer,cur_len,0);
	while(retval < cur_len)
	{
		cur_pos += retval;
		cur_len -= retval;
		retval = send(conn_socket,cur_pos,cur_len,0);
	}
	retval = recv(conn_socket,buffer,65535,0);
	if(retval > 0)
		HttpParse(buffer, retval, conn_socket, file_name, fHandle);
	return 0;

}